<?php


namespace models\Business\Tbk\TbkSdk;


use models\DAO\MemberModel;
use models\DAO\MemberoauthModel;
use models\Exception\Business\MemberException;
use models\Exception\Business\MemberoauthException;
use models\Exception\Business\TbkorderException;
use models\Service\MemberoauthService;
use models\Service\OauthService;
use Tbk\exception\TbkException;
use Yaf\Exception;
use Yaf\Registry;
use Yaf\Session;
use Tbk\Tbk as ylTbk;

class Tbk
{

    const TAOBAO_APP_KEY = '30144205';
    const TAOBAO_APP_SECRET = '8f334c4c9ec2a23a24abb35391d69bc8';
    const TAOBAO_CALLBACK_URL = 'https://api.douziyoupin.com/callback/taobao/oauth';
//    const TAOBAO_CALLBACK_URL = 'http://www.ylmall.com/callback/taobao/oauth';

    /**
     * 获取淘宝oauth的url
     * @return string
     */
    static public function taobaoLogin() {
        $state = uniqid(md5(time()));
        Session::getInstance()->set('YL_TAOBAO_STATE', $state);

        $tbk = new ylTbk();
        $tbk->setAppKey(self::TAOBAO_APP_KEY);
        $tbk->setAppSecret(self::TAOBAO_APP_SECRET);
        $tbk->setOauthCallbackUrl(self::TAOBAO_CALLBACK_URL);
        $tbk->setState($state);

        return $tbk->auth_token->login();
    }

    /**
     * 通过code和state获取用户信息
     * @param string $code
     * @param string $state
     * @return array
     */
    static public function getUserInfo($code = '', $state = '') {
        if (empty($code) || empty($state))
            return [];

        $tbk = new ylTbk();
        $tbk->setAppKey(self::TAOBAO_APP_KEY);
        $tbk->setAppSecret(self::TAOBAO_APP_SECRET);
        $tbk->setOauthCallbackUrl(self::TAOBAO_CALLBACK_URL);
        $tbk->setState($state);

        $tbk->params = [
            'code' => $code
        ];
        $resp = $tbk->auth_token->getUserInfo();
        $user_info = json_decode($resp, true);

        return [
            'open_id' => $user_info['taobao_open_uid'],
            'union_id' => $user_info['taobao_user_id'],
            'avatar' => $user_info['headimgurl'] ? $user_info['headimgurl'] : '0',
            'country' => isset($user_info['country']) ? $user_info['country'] : '中国',
            'province' => isset($user_info['province']) ? $user_info['province'] : '0',
            'city' => isset($user_info['city']) ? $user_info['city'] : '0',
            'nickname' => urldecode($user_info['taobao_user_nick']),
            'sex' => $user_info['city'] ? $user_info['city'] : 0,
            'type' => 4,
            'access_token' => $user_info['access_token'],
            'expired_at' => date('Y-m-d H:i:s', substr($user_info['w1_valid'], 0, 10))
        ];
    }

    /**
     * 刷新access_token
     * @param $access_token
     * @param int $member_id
     * @return mixed
     * @throws TbkException
     */
    static public function refreshToken($access_token, $member_id = 0) {
        $tbk = new ylTbk();
        $tbk->setAppKey(self::TAOBAO_APP_KEY);
        $tbk->setAppSecret(self::TAOBAO_APP_SECRET);

        $tbk->params = [
            'refresh_token' => $access_token
        ];
        try {
            $new_access_token = $tbk->auth_token->refreshToken();

            if (isset($new_access_token['token_result'])) {
                $res = json_decode($new_access_token['token_result'], true);
                $update_arr = ['expired_at' => date('Y-m-d H:i:s', substr($res['refresh_token_valid_time'], 0, 10)),
                    'access_token' => $res['access_token']];

                // 通过member_id查找oauth_id，并修改oauth_id的access_token和expired_at
                $id = $member_id !== 0 ? $member_id : Registry::get('jwt_info')->id;
                $sql = "SELECT o.`id` FROM `oauth` AS o LEFT JOIN `memberoauth` AS mo ON mo.`oauth_id` = o.`id` WHERE mo.`member_id` = " . $id . " AND o.`type` = 4";
                $oauth_info = MemberoauthModel::getInstance()->query($sql);
                if (empty($oauth_info))
                    throw new MemberoauthException(MemberoauthException::MEMBEROAUTH_IS_NOT_EXISTS, MemberoauthException::MEMBEROAUTH_IS_NOT_EXISTS_NO);
                OauthService::getInstance()->update($update_arr, $oauth_info[0]['id']);

                return $res['access_token'];
            }
        } catch (TbkException $e) {
            throw $e;
        } catch (\Exception $e) {
            exit($e->getMessage());
        }

    }

    static public function getTbkOrderMemberIdBySn($sn) {
        $oauth = OauthService::getInstance()->getList(1, 999999, 'desc', 'id', [
            'groupOp' => 'AND', 'rules' => [
                ['field' => 'type', 'op' => 'eq', 'data' => 4],
            ]
        ]);
        if (empty($oauth['data']))
            Registry::get('tbk_log')->err('没有淘宝授权登录的用户');

        $oauth_id = $member_id = '';
        $tbk = new ylTbk();
        foreach ($oauth['data'] as $oauth_info) {
            $access_token = $oauth_info['access_token'];
            $tbk->setAppKey(self::TAOBAO_APP_KEY);
            $tbk->setAppSecret(self::TAOBAO_APP_SECRET);

            $times = 0;
            $message = '';
            while ($times <= 1) {
                // session过期 刷新授权并再次获取数据
                if (empty($message) || strpos($message, 'SessionKey') !== false) {
                    if (strpos($message, 'SessionKey') !== false)
                        $access_token = Tbk::refreshToken($access_token);
                    try {
                        $tbk->setSession($access_token);

                        $tbk->params = [
                            'tid' => $sn
                        ];
                        $resp = $tbk->open_uid_order->getTradeBy();
                        break;
                    } catch (TbkException $e) {
                        $message = $e->getMessage();
                    } finally {
                        $times += 1;
                    }
                } else
                    break;
            }

            if (!empty($message))
                Registry::get('tbk_log')->err('获取订单所有者接口报错:' . $message);

            if (isset($resp['open_uid']) && $oauth_info['open_id'] == $resp['open_uid']) {
                $oauth_id = $oauth_info['id'];
                break;
            }
        }

        if ($oauth_id) {
            $member_oauth = MemberoauthService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'oauth_id', 'op' => 'eq', 'data' => $oauth_id]
            ]]);
            $member_id = $member_oauth['member_id'];
        }

        return $member_id;
    }

    /**
     * 调用tbk接口，通过订单编号判断当前用户的淘宝授权登录的open_id与接口返回的是否一致
     * @param array $parameters
     * @return bool
     * @throws MemberException
     * @throws TbkException
     * @throws TbkorderException
     */
    static public function rebate($parameters = []) {
        try {
            $sql = "SELECT o.`access_token`, o.`open_id` FROM `oauth` AS o LEFT JOIN `memberoauth` AS mo ON o.`id` = mo.`oauth_id` WHERE mo.`member_id` = '" . $parameters['id'] . "'";
            $access_token = MemberModel::getInstance()->query($sql);
            if (empty($access_token))
                throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
        } catch (\Exception $e) {
            throw new MemberException(MemberException::MEMBER_IS_NOT_EXISTS, MemberException::MEMBER_IS_NOT_EXISTS_NO);
        }

        $open_id = $access_token[0]['open_id'];
        $access_token = $access_token[0]['access_token'];

        $tbk = new ylTbk();
        $tbk->setAppKey(self::TAOBAO_APP_KEY);
        $tbk->setAppSecret(self::TAOBAO_APP_SECRET);

        $times = 0;
        $message = '';
        while ($times <= 1) {
            // session过期 刷新授权并再次获取数据
            if (empty($message) || $message == 'SessionKey非法') {
                if ($message == 'SessionKey非法')
                    $access_token = Tbk::refreshToken($access_token);
                try {
                    $tbk->setSession($access_token);

                    $tbk->params = [
                        'tid' => $parameters['sn']
                    ];
                    $resp = $tbk->open_uid_order->getTradeBy();
                    break;
                } catch (TbkException $e) {
                    $message = $e->getMessage();
                } finally {
                    $times += 1;
                }
            } else
                break;
        }

        if (!empty($message))
            throw new TbkorderException($message, 404);

        if (isset($resp['open_uid']))
            return $open_id == $resp['open_uid'];
        else
            throw new TbkorderException(TbkorderException::TBKORDER_IS_NOT_EXISTS, TbkorderException::TBKORDER_IS_NOT_EXISTS_NO);

    }

    static public function getProductInfo($item_id) {
        $tbk = new ylTbk();
        $tbk->setAppKey(self::TAOBAO_APP_KEY);
        $tbk->setAppSecret(self::TAOBAO_APP_SECRET);

        try {

            $tbk->params = [
                'num_iids' => $item_id
            ];
            $result = $tbk->tbk_item->infoGet();
            $result = $result['results']['n_tbk_item'][0];

            return [
                'product_id' => $result['num_iid'],
                'type' => 1,
                'title' => $result['title'],
                'short_title' => $result['title'],
                'category_id' => '14',
                'desc' => $result['title'],
                'article' => $result['title'],
                'pic' => str_replace(['.jpg', '.png', '.jpeg', '.gif'],
                    ['.jpg_.webp', '.png_.webp', '.jpeg_.webp', '.gif_.webp'], $result['pict_url']),
                'image' => str_replace(['.jpg', '.png', '.jpeg', '.gif'],
                    ['.jpg_.webp', '.png_.webp', '.jpeg_.webp', '.gif_.webp'], $result['pict_url']),
                'video_id' => 0,
                'stats' => 1,
                'recommend' => 0,
                'price' => isset($result['zk_final_price']) && $result['zk_final_price'] != 0 ? $result['zk_final_price'] :
                    $result['reserve_price'],
                'today_sales' => 0,
                'sales' => $result['volume'],
                'sales_in_2_hours' => 0,
                'activity_type' => 0,
                'activity_link' => 0,
                'general_index' => 0
            ];
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage(), 404);
        }
    }

}
